package com.suxin.ratelimit.repository;

import com.suxin.ratelimit.Rate;
import com.suxin.ratelimit.properties.RateLimiterProperties;

import java.util.concurrent.TimeUnit;

/**
 * @author Tang
 * @classname AbstractRateLimiter
 * @description [ 数据库 & 内存方式 ]
 * @date 2021/7/14 22:45
 */
public abstract class AbstractRateLimiter implements RateLimiter {

    @Override
    public Rate consumer(RateLimiterProperties.Policy policy, String key) {
        // 1.获取 Rate
        Rate rate = this.create(policy, key);
        // 2.尝试更新次数
        this.updateRate(rate);
        // 3.保存策略
        this.saveRate(rate);
        return rate;
    }

    /**
     * 更新 单位时间的次数
     * @param rate
     */
    private void updateRate(final Rate rate) {
        rate.setLimit(Math.min(-1,rate.getLimit() - 1));
    }

    /**
     * 创建 & 刷新 key
     * @param policy
     * @param key
     * @return
     */
    private Rate create(final RateLimiterProperties.Policy policy, final String key) {
        Rate rate = this.getRate(key);
        if (isExpired(rate)) {
            // 过期的话，重新创建一条限流key,信息
            final Long limit = policy.getLimit();
            final Long refreshInterval = policy.getRefreshInterval();
            final Long expire = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(refreshInterval);
            rate = new Rate(null, key, refreshInterval, limit, expire);
        }
        return rate;
    }

    /**
     * 判断 指定时间内key是否过期
     * @param rate
     * @return
     */
    private boolean isExpired(final Rate rate) {
        return rate == null || (rate.getExpireTime() < System.currentTimeMillis());
    }

    public abstract Rate getRate(String key);

    public abstract void saveRate(Rate value);
}